# -*- encoding:utf-8 -*-
# @time: 2023/4/8 20:26
# @author: Maxs_hu
import datetime
import random

from django import forms
from django.core.exceptions import ValidationError
from django.db.models import F
from django.shortcuts import redirect
from django.shortcuts import render
from django.urls import reverse
from django_redis import get_redis_connection
from django.contrib import messages
from django.conf import settings
from django.db import transaction

from utils.pager import pagination
from web import models


def order_list(request):
    queryset = models.Order.objects.filter(customer_id=request.user_obj.id).order_by('-id')  # 倒序
    if not queryset:
        errors = '抱歉, 这里没有数据...'
        context = {
            'errors': errors
        }
        return render(request, 'order_list.html', context)
    pager = pagination(request, queryset)
    context = {
        'show_data': pager.show_data,
        'pager_string': pager.html(),
    }
    return render(request, 'order_list.html', context)


class addOrderModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.fields['url'].help_text = '示例: https://m.yangshipin.cn/video?type=0&vid=v000013ur6h'

        self.price_list = []
        text_list = []
        price_obj = models.PricePolicy.objects.all().order_by('count')
        for item in price_obj:
            count = item.count
            price = item.price
            unit_price = price / count
            text_list.append('>={}, ¥{}/条'.format(count, unit_price))
            self.price_list.append([count, '>={}, ¥{}/条'.format(count, unit_price), unit_price])
        # print(self.price_list)
        if text_list:
            self.fields['count'].help_text = " || ".join(text_list)
        else:
            self.fields['count'].help_text = '请联系管理员设置价格'

        for name, field in self.fields.items():
            field.widget.attrs['class'] = 'form-control'

    class Meta:
        model = models.Order
        fields = ['url', 'count']
        widgets = {
            'url': forms.URLInput(attrs={'placeholder': '请输入视频地址'}),
            'count': forms.NumberInput(attrs={'placeholder': '请输入个数'}),
        }
        error_messages = {
            'url': {
                'required': '不能为空',
                'invalid': '格式错误'
            },
            'count': {
                'required': '不能为空',
                'invalid': '格式错误'
            }
        }

    def cleaned_count(self):  # 记住这里cleaned + 字段名
        # 判断是否设置了价格
        if not self.price_list:
            raise ValidationError('请联系管理员设置价格')

        # 判断是否小于最小个数
        count = self.cleaned_data['count']
        min_count = self.price_list[0][0]
        if count < min_count:
            raise ValidationError("最低支持数量为:{}".format(min_count))


def order_list_add(request):
    global unit_price
    if request.method == 'GET':
        form = addOrderModelForm()
        return render(request, 'order_list_add.html', {'form': form})

    form = addOrderModelForm(data=request.POST)
    if not form.is_valid():
        return render(request, 'order_list_add.html', {'form': form})
    # 获取count. url
    count = form.cleaned_data['count']
    url = form.cleaned_data['url']

    # 1. 根据数量获取单价. 并计算出单价
    price_list = form.price_list
    price_list.reverse()
    for item in price_list:
        temp_count, _, unit_price = item
        if count >= temp_count:
            break
    total_price = count * unit_price

    try:
        with transaction.atomic():  # 创建事务. 将数据库操作包括在内
            # 2. 当前客户的级别. 计算出折扣之后的价格
            cus_obj = models.Customer.objects.filter(id=request.user_obj.id).select_related(
                'level').select_for_update().first()  # 加上排它锁
            # print(cus_obj.level.percent)  # 跨表操作
            real_price = total_price * cus_obj.level.percent / 100

            # 3. 判断账户余额够不够
            if cus_obj.balance < real_price:
                form.add_error('count', '穷逼哈哈哈, 余额不足')
                return render(request, 'order_list_add.html', {'form': form})

            # 4. 创建订单
            # 4.1 生成订单号
            part1 = int(datetime.datetime.now().strftime('%Y%m%d%H%M%S%f'))
            part2 = random.randint(1000000, 99999999)
            oid = part1 + part2
            # 4.2 爬虫获取播放量... -> 网络请求不要放在事务中. 影响性能
            old_view_count = 10000
            # 4.3 客户ID = 当前登录用的ID
            customer_id = request.user_obj.id
            # 4.4 生成订单
            form.instance.oid = oid
            form.instance.price = total_price  # 原价
            form.instance.real_price = real_price  # 真实价格
            form.instance.old_view_count = old_view_count
            form.instance.customer_id = customer_id
            form.save()

            # 5. 账号扣款 -> 使用F查询更新数据
            models.Customer.objects.filter(id=request.user_obj.id).select_related('level').update(
                balance=F('balance') - real_price)
            # cus_obj.balance = cus_obj.balance - real_price
            # cus_obj.save()

            # 6. 生成交易记录
            models.TransactionRecord.objects.create(
                charge_type=3,  # 创建订单
                customer_id=customer_id,
                amount=real_price,
                order_oid=oid,
            )

            # 7. 写入队列(redis)
            conn = get_redis_connection('default')
            from Order.settings import REDIS_KEY
            conn.lpush(REDIS_KEY, oid)  # 将数据放入队列中
    except Exception as e:
        form.add_error('count', '创建订单失败')
        return render(request, 'order_list_add.html', {'form': form})
    return redirect(reverse('order_list'))


def order_list_cancel(request, pk):
    """ 撤单 """
    # 查询订单当前状态为未执行. 并且customer_id为当前用户id. 防止别人卡bug
    order_obj = models.Order.objects.filter(id=pk, active=1, status=1, customer_id=request.user_obj.id).first()
    if not order_obj:
        # 添加message. 自定义MESSAGE_TAG中 error -> 50
        # 源码中 C:\Users\86183\AppData\Local\Programs\Python\Python39\Lib\site-packages\django\contrib\messages\utils.py
        messages.add_message(request, settings.MESSAGE_DANGER_TAG, '订单不存在')  # settings.MESSAGE_DANGER_TAG -> 50
        return redirect(reverse('order_list'))
    try:
        with transaction.atomic():
            # 1. 订单状态变成(5, '已撤单')
            models.Order.objects.filter(id=pk, active=1, status=1, customer_id=request.user_obj.id).update(status=5)

            # 2. 归还金额到客户的账户
            models.Customer.objects.filter(id=request.user_obj.id).update(balance=F("balance") + order_obj.real_price)

            # 3. 添加交易记录
            models.TransactionRecord.objects.create(
                charge_type=5,
                customer_id=request.user_obj.id,
                amount=order_obj.real_price,
                order_oid=order_obj.oid
            )

            # 4. 撤单成功了
            messages.add_message(request, messages.SUCCESS, '撤单成功!')  # messages.SUCCESS -> 25
            from django.contrib.messages.api import get_messages
            return redirect(reverse('order_list'))

    except Exception as e:
        messages.add_message(request, settings.MESSAGE_DANGER_TAG, '订单不存在')  # settings.MESSAGE_DANGER_TAG -> 50
        return redirect(reverse('order_list'))

